
#include "MediaInput.hh"
#include "Err.hh"
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/poll.h>

FramedSource* MediaInput::VideoSource = NULL;
FramedSource* MediaInput::AudioSource = NULL;

MediaInput* MediaInput::createNew(UsageEnvironment& env) {
	return new MediaInput(env);
}

FramedSource* MediaInput::videoSource() {
	if (VideoSource == NULL) {
		VideoSource = new RealVideoSource(envir(), *this);
	}
	return VideoSource;
}

FramedSource* MediaInput::audioSource() {
	if (AudioSource == NULL) {
		AudioSource = new RealVideoSource(envir(), *this);
	}
	return AudioSource;
}

MediaInput::MediaInput(UsageEnvironment& env)
	: Medium(env) {
}

MediaInput::~MediaInput() {
}

RealMediaSource::RealMediaSource(UsageEnvironment& env, MediaInput& input)
	: FramedSource(env), fInput(input) {
}

RealMediaSource::~RealMediaSource() {
	envir().taskScheduler().turnOffBackgroundReadHandling(fFileNo);
}

void RealMediaSource::incomingDataHandler(RealMediaSource* source, int /*mask*/) {
	source->incomingDataHandler1();
}

int RealMediaSource::mediaConnect (unsigned short port)
{
	struct sockaddr_in addr;
	int s;

	s = ::socket(AF_INET, SOCK_STREAM, 0);
	if (s < 0)
		return -1;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	if (::connect (s, (struct sockaddr *) &addr, sizeof (struct sockaddr)) == -1) {
		fprintf (stderr, "RealMediaSource connect() error!\n");
		goto err;
	}
	return s;
err:
	::close (s);
	return -1;
}

void RealMediaSource::doGetNextFrame() {
	// Await the next incoming data on our FID:
	envir().taskScheduler().turnOnBackgroundReadHandling(fFileNo,
	       (TaskScheduler::BackgroundHandlerProc*)&incomingDataHandler, this);
}

void RealMediaSource::incomingDataHandler1() {
	// Read the data from our file into the client's buffer:
	readFromFile();
	// Stop handling any more input, until we're ready again:
	envir().taskScheduler().turnOffBackgroundReadHandling(fFileNo);

	// Tell our client that we have new data:
	afterGetting(this);
}

RealVideoSource::RealVideoSource(UsageEnvironment& env, MediaInput& input)
	: RealMediaSource(env, input) {
	gettimeofday(&fPresentationTime, NULL);
	fFileNo = mediaConnect (9998);
}

RealVideoSource::~RealVideoSource() {
	fInput.VideoSource = NULL;
	if (fFileNo > 0) {
		envir().taskScheduler().turnOffBackgroundReadHandling(fFileNo);
		::close (fFileNo);
		fFileNo = -1;
	}
}

void RealVideoSource::readFromFile() {
	int ret;

	ret = ::recv (fFileNo, fTo, fMaxSize, 0);
	if (ret > 0) {
		gettimeofday(&fPresentationTime, NULL);
		fFrameSize = ret;
		fNumTruncatedBytes = 0;
	}
}


RealAudioSource::RealAudioSource(UsageEnvironment& env, MediaInput& input)
	: RealMediaSource(env, input) {
}

RealAudioSource::~RealAudioSource() {
	fInput.AudioSource = NULL;
}

void RealAudioSource::readFromFile() {
}
